package cn.youqu.happy.module.youqu.service.userComment;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.youqu.happy.framework.common.pojo.PageResult;
import cn.youqu.happy.framework.common.util.string.StrUtils;
import cn.youqu.happy.module.member.dal.dataobject.user.MemberUserDO;
import cn.youqu.happy.module.member.service.user.MemberUserService;
import cn.youqu.happy.module.youqu.controller.admin.userAssess.vo.UserAssessUpdateReqVO;
import cn.youqu.happy.module.youqu.controller.admin.userComment.vo.UserCommentCreateReqVO;
import cn.youqu.happy.module.youqu.controller.admin.userComment.vo.UserCommentExportReqVO;
import cn.youqu.happy.module.youqu.controller.admin.userComment.vo.UserCommentPageReqVO;
import cn.youqu.happy.module.youqu.controller.admin.userComment.vo.UserCommentUpdateReqVO;
import cn.youqu.happy.module.youqu.controller.app.userComment.vo.AppUserCommentDetailPageReqVO;
import cn.youqu.happy.module.youqu.controller.app.userComment.vo.AppUserCommentDetailRespVO;
import cn.youqu.happy.module.youqu.controller.app.userComment.vo.AppUserCommentPublishReqVO;
import cn.youqu.happy.module.youqu.controller.app.userComment.vo.AppUserCommentReplyAssessReqVO;
import cn.youqu.happy.module.youqu.convert.userAssess.UserAssessConvert;
import cn.youqu.happy.module.youqu.convert.userComment.UserCommentConvert;
import cn.youqu.happy.module.youqu.dal.dataobject.userAssess.UserAssessDO;
import cn.youqu.happy.module.youqu.dal.dataobject.userComment.UserCommentDO;
import cn.youqu.happy.module.youqu.dal.dataobject.userTell.UserTellDO;
import cn.youqu.happy.module.youqu.dal.mysql.userComment.UserCommentMapper;
import cn.youqu.happy.module.youqu.enums.userTell.UserTellStatusEnum;
import cn.youqu.happy.module.youqu.service.userAssess.UserAssessService;
import cn.youqu.happy.module.youqu.service.userTell.UserTellService;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static cn.youqu.happy.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.youqu.happy.module.member.enums.ErrorCodeConstants.USER_NOT_EXISTS;
import static cn.youqu.happy.module.youqu.enums.ErrorCodeConstants.*;

/**
 * 用户回复 Service 实现类
 *
 * @author 王其岩 20112001045
 */
@Service
@Validated
public class UserCommentServiceImpl implements UserCommentService {

    @Resource
    private UserCommentMapper userCommentMapper;

    @Resource
    @Lazy
    private UserTellService userTellService;

    @Resource
    @Lazy
    private MemberUserService memberUserService;

    @Resource
    @Lazy
    private UserAssessService userAssessService;

    @Override
    public Integer publishUserComment(UserCommentCreateReqVO createReqVO) {
        // 插入
        UserCommentDO userComment = UserCommentConvert.INSTANCE.convert(createReqVO);
        userCommentMapper.insert(userComment);
        // 返回
        return userComment.getId();
    }

    @Override
    public Integer publishUserComment(AppUserCommentPublishReqVO publishReqVO, Long uid) {

        UserCommentDO convert = UserCommentConvert.INSTANCE.convert(publishReqVO);
        //如果含有 pid 判断pid 是否存在
        if (publishReqVO.getPid() != null) {
            this.validateUserCommentExists(publishReqVO.getPid(), publishReqVO.getTellId());
            UserCommentDO userComment = getUserComment(publishReqVO.getPid());
            if (userComment == null) {
                throw exception(USER_COMMENT_NOT_EXISTS);
            } else {
                //有 pid 就是回复
                //设置回复用户
                convert.setReplyUid(userComment.getUid());
                //设置回复说说 已在convert 中转换
            }
        }


        //校验说说是否存在
        UserTellDO userTell = userTellService.getUserTell(convert.getTellId());
        if (userTell == null) {
            throw exception(USER_TELL_NOT_EXISTS);
        }
        //如果仅自己可见 其他人不能评论
        if (userTell.getTellStatus().equals(UserTellStatusEnum.PRIVATE_OWN.getStatus())) {
            if (!userTell.getUid().equals(uid)) {
                throw exception(USER_COMMENT_CAN_NOT_MAKE_COMMENT);
            }
        } else if (userTell.getTellStatus().equals(UserTellStatusEnum.PRIVATE_PARTNER.getStatus())) {
            //如果队友可见 其他人不能评论
            //判断用户说说是否包含此用户
            String partners = userTell.getPartners();
            if (partners == null) {
                throw exception(USER_COMMENT_CAN_NOT_MAKE_COMMENT);
            } else {
                List<String> strings = StrUtils.stringConvertToList(partners);
                if (strings.stream().noneMatch(item -> String.valueOf(uid).equals(item))) {
                    throw exception(USER_COMMENT_CAN_NOT_MAKE_COMMENT);
                }
            }
        }
        //设置回复用户信息
        MemberUserDO user = memberUserService.getUser(uid);
        convert.setUid(user.getId());
        convert.setAvatar(user.getAvatar());
        convert.setNickName(user.getNickname());

        //插入评论
        userCommentMapper.insert(convert);
        return convert.getId();
    }

    @Override
    public void updateUserComment(UserCommentUpdateReqVO updateReqVO) {
        // 校验存在
        this.validateUserCommentExists(updateReqVO.getId());
        // 更新
        UserCommentDO updateObj = UserCommentConvert.INSTANCE.convert(updateReqVO);
        userCommentMapper.updateById(updateObj);
    }


    @Override
    public void deleteUserComment(Integer id) {
        // 校验存在
        this.validateUserCommentExists(id);
        // 删除
        userCommentMapper.deleteById(id);
    }

    @Override
    public void deleteUserComment(Integer id, Long uid) {

        UserCommentDO userCommentDO = userCommentMapper.selectById(id);
        //校验是否存在
        if (userCommentDO == null) {
            throw exception(USER_COMMENT_NOT_EXISTS);
        }

        //校验是否是自己的
        if (!Objects.equals(userCommentDO.getUid(), uid)) {
            //校验是否是楼主说说的评论
            Integer tellId = userCommentDO.getTellId();
            if (tellId == null) {
                throw exception(USER_TELL_NOT_EXISTS);
            }
            UserTellDO userTell = userTellService.getUserTell(tellId);
            if (!Objects.equals(userTell.getUid(), uid)) {
                throw exception(USER_COMMENT_NOT_HAVE_POWER_DELETE_COMMENT);
            }
        }
        // 删除
        userCommentMapper.deleteById(id);
    }

    private void validateUserCommentExists(Integer id) {
        if (userCommentMapper.selectById(id) == null) {
            throw exception(USER_COMMENT_NOT_EXISTS);
        }
    }

    private void validateUserCommentExists(Integer id, Integer tellId) {
        if (userCommentMapper.findOneByIdAndTellId(id, tellId) == null) {
            throw exception(USER_COMMENT_NOT_EXISTS);
        }
    }

    //校验用户是否拥有此条评论
    private void validateUserOwnUserComment(Integer id, Long uid) {
        UserCommentDO userCommentDO = userCommentMapper.selectById(id);
        if (userCommentDO == null) {
            throw exception(USER_COMMENT_NOT_EXISTS);
        } else {
            if (!Objects.equals(userCommentDO.getUid(), uid)) {
                throw exception(USER_COMMENT_NOT_BELONG_TO_YOU);
            }
        }
    }

    @Override
    public UserCommentDO getUserComment(Integer id) {
        return userCommentMapper.selectById(id);
    }

    @Override
    public UserCommentDO getUserComment(Integer id, Long uid) {
        return userCommentMapper.findByIdAndUid(id, uid);
    }

    @Override
    public List<UserCommentDO> getUserCommentList(Collection<Integer> ids) {
        return userCommentMapper.selectBatchIds(ids);
    }

    //筛选用户拥有的评论
    private List<UserCommentDO> filterUserOwnUserComment(List<UserCommentDO> userCommentDOS, Long uid) {
        return userCommentDOS.stream().filter(item -> Objects.equals(item.getUid(), uid)).collect(Collectors.toList());
    }

    //筛选自己的评价 评价自己的
    private List<UserCommentDO> filterUserCanSeeUserComment(List<UserCommentDO> userCommentDOS, Long uid) {
        return userCommentDOS.stream().filter(item -> Objects.equals(item.getUid(), uid) || Objects.equals(item.getReplyUid(), uid)).collect(Collectors.toList());
    }

    @Override
    public List<UserCommentDO> getUserCommentList(Collection<Integer> ids, Long uid) {
        List<UserCommentDO> userCommentDOS = userCommentMapper.selectBatchIds(ids);
        //筛选用户可见的评论
        return filterUserCanSeeUserComment(userCommentDOS, uid);
    }

    @Override
    public PageResult<UserCommentDO> getUserCommentPage(UserCommentPageReqVO pageReqVO) {
        return userCommentMapper.selectPage(pageReqVO);
    }

    @Override
    public PageResult<UserCommentDO> getUserCommentPage(UserCommentPageReqVO pageReqVO, Long uid) {
        PageResult<UserCommentDO> userCommentDOPageResult = userCommentMapper.selectPage(pageReqVO);
        List<UserCommentDO> list = userCommentDOPageResult.getList();
        //筛选用户可见的评论
        List<UserCommentDO> userCommentDOS = filterUserCanSeeUserComment(list, uid);
        userCommentDOPageResult.setList(userCommentDOS);
        userCommentDOPageResult.setTotal((long) userCommentDOS.size());
        return userCommentDOPageResult;
    }

    @Override
    public PageResult<Tree<AppUserCommentDetailRespVO>> getUserCommentDetailPageByTellId(AppUserCommentDetailPageReqVO detailPageReqVO, Long uid) {
        UserTellDO userTell = userTellService.getUserTell(detailPageReqVO.getTellId());

        if (userTell == null) {
            throw exception(USER_TELL_NOT_EXISTS);
        }

        //校验用户是否可见说说
        if (!userTellService.validateUserCanSeeUserTell(detailPageReqVO.getTellId(), uid)) {
            throw exception(USER_COMMENT_NOT_HAVE_POWER_MAKE_COMMENT);
        }

        UserCommentPageReqVO convert = UserCommentConvert.INSTANCE.convert(detailPageReqVO);
        PageResult<UserCommentDO> userCommentDOPageResult = userCommentMapper.selectPage(convert);
        List<UserCommentDO> list = userCommentDOPageResult.getList();
        System.out.println(list);
        //转为树状结构
        TreeNodeConfig config = new TreeNodeConfig();
        config.setParentIdKey("pid");
        config.setChildrenKey("commentReplyList");
        List<Tree<AppUserCommentDetailRespVO>> build = TreeUtil.build(list, null, config, (object, tree) -> {
            Field[] fields = ReflectUtil.getFieldsDirectly(object.getClass(), false);
            for (Field field : fields) {
                if (!field.getName().equals("remark")) {
                    String fieldName = field.getName();
                    Object fieldValue = ReflectUtil.getFieldValue(object, field);
                    tree.putExtra(fieldName, fieldValue);
                }
            }
            //设置是否是楼主
            tree.putExtra("isHost", Objects.equals(object.getUid(), userTell.getUid()));
            tree.putExtra("createTime", object.getCreateTime());
        });
        PageResult<Tree<AppUserCommentDetailRespVO>> appUserCommentDetailRespVOPageResult = new PageResult<>();
        appUserCommentDetailRespVOPageResult.setList(build);
        appUserCommentDetailRespVOPageResult.setTotal((long) build.size());

        return appUserCommentDetailRespVOPageResult;
    }

    @Override
    public List<UserCommentDO> getUserCommentList(UserCommentExportReqVO exportReqVO) {
        return userCommentMapper.selectList(exportReqVO);
    }

    @Override
    @Transactional
    public Integer replyAssessUserComment(AppUserCommentReplyAssessReqVO replyAssessReqVO, Long loginUserId) {
        UserAssessDO userAssess = userAssessService.getUserAssess(replyAssessReqVO.getAssessId());
        if (userAssess == null) {
            throw exception(USER_ASSESS_NOT_EXISTS);
        }
        //判断评价是不是评价的自己
        if (Objects.equals(userAssess.getTargetId(), loginUserId)) {
            throw exception(USER_COMMENT_NOT_HAVE_POWER_REPLY_ASSESS);
        }
        //判断是否已经回复
        if (userAssess.getReplayId() != null) {
            throw exception(USER_ASSESS_ALREADY_REPLY_ASSESS);
        }
        UserCommentDO convert = UserCommentConvert.INSTANCE.convert(replyAssessReqVO);

        //设置发表回复的人
        convert.setUid(loginUserId);
        //设置回复的人 谁发布的评价就回复谁
        convert.setReplyUid(userAssess.getUid());
        MemberUserDO user = memberUserService.getUser(loginUserId);
        if (user == null) {
            throw exception(USER_NOT_EXISTS);
        }
        convert.setNickName(user.getNickname());
        convert.setAvatar(user.getAvatar());

        userCommentMapper.insert(convert);
        //设置回复评价的id
        userAssess.setReplayId(convert.getId());
        UserAssessUpdateReqVO updateReqVO = UserAssessConvert.INSTANCE.convert1(userAssess);
        userAssessService.updateUserAssess(updateReqVO);
        return convert.getId();
    }

    @Override
    public void updateUserInfoToUserComment(String nickname, String avatar, Long uid) {
        if (nickname != null) {
            userCommentMapper.updateNickNameByUid(nickname, uid);
        }
        if (avatar != null) {
            userCommentMapper.updateAvatarByUid(avatar, uid);
        }
    }
}
